<?php
/**
 * 统一推送守护进程
 * 整合所有推送功能到一个单文件，轮询检查不同类型的推送需求
 */
include('confing/common.php');
include('wxpusher/wxpusher.class.php');
include('push_api.php'); // 引入推送API函数

// 设置脚本执行时间，防止超时
set_time_limit(0);
ignore_user_abort(true);

// WxPusher配置
$Token = ''; // 替换为你的Token
$wxpusher = new Wxpusher($Token);

// 检查间隔时间（秒）
$nextMethodDelay = 10; // 每个方法之间等待10秒
$fullCycleDelay = 60; // 完成所有方法后等待60秒再开始新一轮检查
$pushDelay = 3; // 每次推送间隔3秒，避免API限制

// 余额预警阈值
$balanceThreshold = 10; // 余额低于10积分时发送预警

// 日志输出函数
function logMessage($message) {
    echo date('Y-m-d H:i:s') . " - " . $message . "\n";
}

logMessage("统一推送守护进程启动");
logMessage("每个方法间隔{$nextMethodDelay}秒，完整循环后等待{$fullCycleDelay}秒");

// 无限循环检查
while (true) {
    try {
        // 1. 检查订单完成推送
        logMessage("开始执行：订单完成推送检查");
        checkOrderCompletePush($DB, $wxpusher);
        sleep($nextMethodDelay);
        
        // 2. 检查系统公告推送
        logMessage("开始执行：系统公告推送检查");
        checkSystemNoticePush($DB, $wxpusher);
        sleep($nextMethodDelay);
        
        // 3. 检查余额不足预警
        logMessage("开始执行：余额不足预警检查");
        checkUsersBalance($DB, $wxpusher, $balanceThreshold);
        sleep($nextMethodDelay);
        
        // 4. 检查登录安全提醒
        logMessage("开始执行：登录安全提醒检查");
        checkLoginSecurityPush($DB, $wxpusher);
        sleep($nextMethodDelay);
        
        // 5. 检查订单异常通知
        logMessage("开始执行：订单异常通知检查");
        checkOrderExceptionPush($DB, $wxpusher);
        sleep($nextMethodDelay);
        
        // 6. 检查订单退款通知
        logMessage("开始执行：订单退款通知检查");
        checkOrderRefundPush($DB, $wxpusher);
        sleep($nextMethodDelay);
        
        // 7. 检查新增代理通知
        logMessage("开始执行：新增代理通知检查");
        checkNewAgentPush($DB, $wxpusher);
        sleep($nextMethodDelay);
        
        // 8. 检查考试开始提醒
        logMessage("开始执行：考试开始提醒检查");
        checkUpcomingExams($DB, $wxpusher);
        sleep($nextMethodDelay);
        
        // 9. 检查游客订单通知
        logMessage("开始执行：游客订单通知检查");
        checkTouristOrderPush($DB, $wxpusher);
        
        // 完成所有检查，等待下一轮循环
        logMessage("完成本轮所有推送检查，等待{$fullCycleDelay}秒后开始下一轮检查");
        sleep($fullCycleDelay);
    } catch (Exception $e) {
        logMessage("执行过程中发生错误: " . $e->getMessage());
        sleep(30); // 出错后等待30秒重试
    }
}

/**
 * 检查需要推送订单完成通知的订单
 */
function checkOrderCompletePush($DB, $wxpusher) {
    global $pushDelay;
    
    // 查询需要推送的订单
    // 条件：
    // 1. 订单状态为"已完成"或"学习完成"
    // 2. 用户已绑定pushUid
    // 3. 用户开启了订单完成推送（orderComplete=1）
    // 4. 订单未被推送过（pushStatus=0 或 NULL）
    // 5. 添加时间字段"addtime"早于2025-05-10的订单记录
    $orders = $DB->query("SELECT o.*, u.pushUid 
                         FROM qingka_wangke_order o 
                         JOIN qingka_wangke_user u ON o.uid = u.uid 
                         WHERE (o.status = '已完成' OR o.status = '学习完成')
                         AND u.pushUid IS NOT NULL 
                         AND u.orderComplete = '1' 
                         AND (o.pushStatus = '0' OR o.pushStatus IS NULL)
                         AND o.addtime > '2025-05-14'
                         LIMIT 20");
    
    $count = 0;
    
    while ($order = $DB->fetch($orders)) {
        // 发送推送
        $result = sendOrderCompletePush($wxpusher, $order['pushUid'], $order);
        
        // 更新订单推送状态
        $pushStatus = $result ? '1' : '2'; // 1=成功，2=失败
        $DB->query("UPDATE qingka_wangke_order SET pushStatus = '$pushStatus' WHERE oid = '{$order['oid']}'");
        
        if ($result) {
            // 记录推送日志
            $now = date('Y-m-d H:i:s');
            $title = "订单完成通知";
            $content = "您的订单 {$order['oid']} ({$order['kcname']}) 已完成";
            $DB->query("INSERT INTO push_logs (uid, order_id, type, title, content, status, push_time) 
                      VALUES ('{$order['uid']}', '{$order['oid']}', 'order_complete', '$title', '$content', '1', '$now')");
        }
        
        $count++;
        sleep($pushDelay); // 延迟，避免API限制
    }
    
    logMessage("订单完成推送检查完毕，处理 {$count} 条记录");
}

/**
 * 检查系统公告并推送
 */
function checkSystemNoticePush($DB, $wxpusher) {
    global $pushDelay;
    
    // 获取最新公告
    $announcement = getLatestAnnouncement();
    if (!$announcement) {
        logMessage("系统公告推送检查完毕，处理 0 条记录");
        return;
    }
    $announcementId = $announcement['id'];
    
    // 查询所有已绑定pushUid且开启公告推送的用户，且从未收到过该公告ID
    // 修复：使用公告ID来确定用户是否收到过该公告，避免重复推送
    // 5. 添加时间字段"addtime"早于2025-05-10的订单记录
    $sql = "SELECT u.uid, u.pushUid FROM qingka_wangke_user u
            WHERE u.pushUid IS NOT NULL
            AND u.sysNotice = '1'
            AND NOT EXISTS (
                SELECT 1 FROM push_logs p
                WHERE p.uid = u.uid
                AND p.type = 'system'
                AND p.content LIKE '%公告ID:{$announcementId}%'
                AND p.push_time > DATE_SUB(NOW(), INTERVAL 24 HOUR)
            )
            LIMIT 20";
    $query = $DB->query($sql);
    $count = 0;
    while ($user = $DB->fetch($query)) {
        // 发送推送
        $result = sendAnnouncementPush($wxpusher, $user['pushUid'], $announcement);
        
        if ($result) {
            // 记录推送日志，添加公告ID用于识别
            $now = date('Y-m-d H:i:s');
            $title = "系统公告：" . $announcement['title'];
            $content = "公告ID:{$announcementId}, " . substr($announcement['content'], 0, 100) . "...";
            $DB->query("INSERT INTO push_logs (uid, type, title, content, status, push_time) 
                      VALUES ('{$user['uid']}', 'system', '" . addslashes($title) . "', '" . addslashes($content) . "', '1', '$now')");
        }
        
        $count++;
        sleep($pushDelay); // 延迟，避免API限制
    }
    
    logMessage("系统公告推送检查完毕，处理 {$count} 条记录");
}

/**
 * 检查所有用户余额并发送预警
 */
function checkUsersBalance($DB, $wxpusher, $threshold) {
    global $pushDelay;
    
    // 查询需要发送预警的用户
    // 条件：
    // 1. 余额低于阈值
    // 2. 已绑定pushUid
    // 3. 开启了余额预警通知(balanceLow=1)
    // 4. 在过去24小时内未收到过预警通知
    $users = $DB->query("SELECT u.uid, u.user, u.name, u.money, u.pushUid 
                         FROM qingka_wangke_user u 
                         WHERE u.money < {$threshold} 
                         AND u.pushUid IS NOT NULL 
                         AND u.pushUid != '' 
                         AND u.balanceLow = '1'
                         AND NOT EXISTS (
                             SELECT 1 FROM push_logs p 
                             WHERE p.uid = u.uid 
                             AND p.type = 'system' 
                             AND p.title = '余额不足预警通知' 
                             AND p.push_time > DATE_SUB(NOW(), INTERVAL 24 HOUR)
                             AND p.status = '1'
                         )
                         LIMIT 20");
    
    $count = 0;
    $success = 0;
    
    while ($user = $DB->fetch($users)) {
        // 发送预警推送
        $result = sendBalanceLowAlert($wxpusher, $user['pushUid'], $user, false);
        
        if ($result) {
            $success++;
        }
        
        $count++;
        sleep($pushDelay); // 延迟，避免API限制
    }
    
    logMessage("余额不足预警检查完毕，处理 {$count} 条记录");
}

/**
 * 检查用户最近两次登录IP，若不同则推送安全提醒
 */
function checkLoginSecurityPush($DB, $wxpusher) {
    global $pushDelay;

    // 查询所有开启了登录安全提醒且已绑定推送的用户
    $users = [];
    $query = $DB->query("SELECT uid, user, name, pushUid FROM qingka_wangke_user WHERE loginSecurity='1' AND pushUid IS NOT NULL AND pushUid != ''");
    while ($row = $DB->fetch($query)) {
        $users[] = $row;
    }
    $count = 0;
    foreach ($users as $user) {
        $uid = $user['uid'];
        // 查询最近两次登录日志（只查type=登录）
        $logRes = $DB->query("SELECT ip, addtime, text FROM qingka_wangke_log WHERE uid='$uid' AND type='登录' ORDER BY addtime DESC LIMIT 2");
        $logs = [];
        while ($log = $DB->fetch($logRes)) {
            $logs[] = $log;
        }
        if (count($logs) < 2) continue; // 没有两次登录
        if ($logs[0]['ip'] == $logs[1]['ip']) continue; // IP相同不推送

        // 检查本次登录addtime是否已推送过（防止重复）
        $lastPush = $DB->get_row("SELECT id FROM push_logs WHERE uid='$uid' AND type='security' AND content LIKE '%" . $DB->escape($logs[0]['addtime']) . "%'");
        if ($lastPush) continue;

        // 获取设备信息
        $device = $logs[0]['text'] ?? '未知设备';
        
        // 准备登录信息
        $loginInfo = [
            'ip' => $logs[0]['ip'],
            'device' => $device,
            'time' => $logs[0]['addtime'],
            'is_test' => false
        ];
        
        // 记录正在处理的登录安全推送
        logMessage("开始处理登录安全推送，用户: {$user['user']}, IP: {$logs[0]['ip']}");
        
        // 发送推送 (sendLoginSecurityAlert函数内部会获取IP位置信息)
        $result = sendLoginSecurityAlert($wxpusher, $user['pushUid'], $loginInfo);
        if ($result) {
            // 记录本次登录addtime到content，防止重复推送
            $DB->query("INSERT INTO push_logs (uid, type, title, content, status, push_time) VALUES ('$uid', 'security', '登录安全提醒', '登录时间: " . $DB->escape($logs[0]['addtime']) . "', '1', NOW())");
            $count++;
        }
        
        sleep($pushDelay);
    }
    
    logMessage("登录安全提醒检查完毕，处理 {$count} 条记录");
}

/**
 * 检查需要推送订单异常通知的订单
 */
function checkOrderExceptionPush($DB, $wxpusher) {
    global $pushDelay;
    
    // 查询需要推送的异常订单
    // 条件：
    // 1. 订单状态包含异常信息（如"登录失败"、"异常"等）
    // 2. 用户已绑定pushUid
    // 3. 用户开启了订单异常推送（orderExceptionNotice=1）
    // 4. 订单未被推送过（pushStatus=0 或 NULL）
    // 5. 避免重复通知同一订单（通过查询push_logs表）
    $orders = $DB->query("SELECT o.*, u.pushUid 
                          FROM qingka_wangke_order o 
                          JOIN qingka_wangke_user u ON o.uid = u.uid 
                          WHERE (o.status LIKE '%密码错误%' OR o.status LIKE '%异常%' OR o.process LIKE '%错误%' OR o.process LIKE '%失败%') 
                          AND u.pushUid IS NOT NULL 
                          AND u.orderExceptionNotice = '1' 
                          AND (o.pushStatus = '0' OR o.pushStatus IS NULL)
                          AND NOT EXISTS (
                              SELECT 1 FROM push_logs 
                              WHERE type = 'order_exception'
                              AND order_id = o.oid
                              AND push_time > DATE_SUB(NOW(), INTERVAL 6 HOUR)
                          )
                          LIMIT 20");
    
    $count = 0;
    
    if ($orders) {
        while ($order = $DB->fetch($orders)) {
            // 准备订单信息
            $orderInfo = [
                'oid' => $order['oid'],
                'kcname' => $order['kcname'],
                'user' => $order['user'],
                'school' => $order['school'],
                'process' => $order['remarks'] ?: $order['status'],
                'time' => date('Y-m-d H:i:s')
            ];
            
            // 发送推送
            $result = sendOrderExceptionNotice($wxpusher, $order['pushUid'], $orderInfo);
            
            // 更新订单推送状态
            $pushStatus = $result ? '1' : '2'; // 1=成功，2=失败
            $DB->query("UPDATE qingka_wangke_order SET pushStatus = '$pushStatus' WHERE oid = '{$order['oid']}'");
            
            if ($result) {
                // 记录推送日志
                $now = date('Y-m-d H:i:s');
                $title = "订单异常通知";
                $content = "您的订单 {$order['oid']} ({$order['kcname']}) 出现异常: {$orderInfo['process']}";
                $DB->query("INSERT INTO push_logs (uid, order_id, type, title, content, status, push_time) 
                          VALUES ('{$order['uid']}', '{$order['oid']}', 'order_exception', '$title', '$content', '1', '$now')");
            }
            
            $count++;
            sleep($pushDelay); // 延迟，避免API限制
        }
    }
    
    logMessage("订单异常推送检查完毕，处理 {$count} 条记录");
}

/**
 * 检查需要推送订单退款通知的订单
 */
function checkOrderRefundPush($DB, $wxpusher) {
    global $pushDelay;
    
    // 查询需要推送的退款订单
    // 条件：
    // 1. 订单状态为"已退款"或包含"退款"关键词
    // 2. 用户已绑定pushUid
    // 3. 用户开启了订单退款推送（orderRefundNotice=1）
    // 4. 订单未被推送过（pushStatus=0 或 NULL）
    // 5. 避免重复通知同一订单（通过查询push_logs表）
    $orders = $DB->query("SELECT o.*, u.pushUid 
                         FROM qingka_wangke_order o 
                         JOIN qingka_wangke_user u ON o.uid = u.uid 
                         WHERE (o.status LIKE '%退款%' OR o.status = '已退款' OR o.process LIKE '%退款%') 
                         AND u.pushUid IS NOT NULL 
                         AND u.orderRefundNotice = '1' 
                         AND (o.pushStatus = '0' OR o.pushStatus IS NULL)
                         AND NOT EXISTS (
                             SELECT 1 FROM push_logs 
                             WHERE type = 'order_refund'
                             AND order_id = o.oid
                             AND push_time > DATE_SUB(NOW(), INTERVAL 24 HOUR)
                         )
                         LIMIT 20");
    
    $count = 0;
    
    if ($orders) {
        while ($order = $DB->fetch($orders)) {
            // 准备订单信息
            $orderInfo = [
                'oid' => $order['oid'],
                'kcname' => $order['kcname'],
                'fees' => $order['fees'],
                'refund_reason' => $order['remarks'] ?: ($order['process'] ?: '系统自动退款'),
                'refund_time' => date('Y-m-d H:i:s')
            ];
            
            // 发送推送
            $result = sendOrderRefundNotice($wxpusher, $order['pushUid'], $orderInfo);
            
            // 更新订单推送状态
            $pushStatus = $result ? '1' : '2'; // 1=成功，2=失败
            $DB->query("UPDATE qingka_wangke_order SET pushStatus = '$pushStatus' WHERE oid = '{$order['oid']}'");
            
            if ($result) {
                // 记录推送日志
                $now = date('Y-m-d H:i:s');
                $title = "订单退款通知";
                $content = "您的订单 {$order['oid']} ({$order['kcname']}) 已退款，金额: {$order['fees']}";
                $DB->query("INSERT INTO push_logs (uid, order_id, type, title, content, status, push_time) 
                          VALUES ('{$order['uid']}', '{$order['oid']}', 'order_refund', '$title', '$content', '1', '$now')");
            }
            
            $count++;
            sleep($pushDelay); // 延迟，避免API限制
        }
    }
    
    logMessage("订单退款推送检查完毕，处理 {$count} 条记录");
}

/**
 * 检查新增代理并发送通知
 */
function checkNewAgentPush($DB, $wxpusher) {
    global $pushDelay;
    
    // 获取最近30分钟内注册的代理
    $timeLimit = date('Y-m-d H:i:s', strtotime('-30 minutes'));
    
    // 查询新增代理，并找出其上级代理
    $query = $DB->query("SELECT u.uid, u.user, u.name, u.addtime, u.ip, u.uuid, 
                          p.pushUid, p.newAgentNotice
                      FROM qingka_wangke_user u 
                      JOIN qingka_wangke_user p ON u.uuid = p.uid
                      WHERE u.addtime > '$timeLimit'
                      AND u.uuid > 0 
                      AND p.pushUid IS NOT NULL 
                      AND p.newAgentNotice = '1'
                      AND NOT EXISTS (
                          SELECT 1 FROM push_logs 
                          WHERE type = 'new_agent'
                          AND push_logs.uid = u.uid
                      )
                      LIMIT 20");
    
    $count = 0;
    
    if ($query) {
        while ($row = $DB->fetch($query)) {
            // 准备推送内容
            $agentInfo = [
                'name' => $row['name'],
                'user' => $row['user'],
                'time' => $row['addtime'],
                'uuid' => $row['uuid'],
                'ip' => $row['ip'] ?: '未知IP'
            ];
            
            // 首先尝试获取IP位置信息（注意：sendNewAgentNotice已经包含获取IP位置的逻辑）
            logMessage("开始处理新增代理推送，代理: {$row['user']}, IP: {$row['ip']}");
            
            // 发送推送
            $result = sendNewAgentNotice($wxpusher, $row['pushUid'], $agentInfo);
            
            if ($result) {
                // 记录推送日志，避免重复推送
                $now = date('Y-m-d H:i:s');
                $title = "新增代理通知";
                $content = "您有新代理加入: {$row['user']}";
                $DB->query("INSERT INTO push_logs (uid, type, title, content, status, push_time) 
                           VALUES ('{$row['uid']}', 'new_agent', '$title', '$content', '1', '$now')");
            }
            
            $count++;
            sleep($pushDelay); // 延迟，避免API限制
        }
    }
    
    logMessage("新增代理推送检查完毕，处理 {$count} 条记录");
}

/**
 * 检查即将开始考试并发送提醒
 */
function checkUpcomingExams($DB, $wxpusher) {
    global $pushDelay;
    
    // 计算时间范围：明天的日期
    $tomorrowStart = date('Y-m-d 00:00:00', strtotime('+1 day'));
    $tomorrowEnd = date('Y-m-d 23:59:59', strtotime('+1 day'));
    
    // 查询明天开始考试的订单
    $sql = "SELECT o.oid, o.uid, o.kcname, o.examStartTime, o.school, o.user, u.pushUid, u.examStartNotice 
            FROM qingka_wangke_order o 
            JOIN qingka_wangke_user u ON o.uid = u.uid 
            WHERE o.examStartTime >= '$tomorrowStart' 
            AND o.examStartTime <= '$tomorrowEnd' 
            AND u.pushUid IS NOT NULL 
            AND u.examStartNotice = '1'
            AND NOT EXISTS (
                SELECT 1 FROM push_logs p 
                WHERE p.order_id = o.oid 
                AND p.type = 'exam_notice' 
                AND p.push_time > DATE_SUB(NOW(), INTERVAL 24 HOUR)
            )
            LIMIT 20";
    
    $query = $DB->query($sql);
    $count = 0;
    
    if ($query) {
        while ($order = $DB->fetch($query)) {
            // 准备考试信息
            $examInfo = [
                'oid' => $order['oid'],
                'kcname' => $order['kcname'],
                'examStartTime' => $order['examStartTime'],
                'school' => $order['school'],
                'user' => $order['user']
            ];
            
            // 发送推送
            $result = sendExamStartNotice($wxpusher, $order['pushUid'], $examInfo);
            
            if ($result) {
                // 记录推送日志，避免重复推送
                $now = date('Y-m-d H:i:s');
                $title = "考试开始提醒";
                $content = "您的课程 {$order['kcname']} 将于明天 {$order['examStartTime']} 开始考试";
                $DB->query("INSERT INTO push_logs (uid, order_id, type, title, content, status, push_time) 
                          VALUES ('{$order['uid']}', '{$order['oid']}', 'exam_notice', '$title', '$content', '1', '$now')");
            }
            
            $count++;
            sleep($pushDelay); // 延迟，避免API限制
        }
    }
    
    logMessage("考试开始提醒检查完毕，处理 {$count} 条记录");
}

/**
 * 检查并推送游客订单通知
 */
function checkTouristOrderPush($DB, $wxpusher) {
    global $pushDelay;
    
    // 查询需要推送的游客订单
    // 条件：
    // 1. 订单类型为 tourist 或 tourist1
    // 2. 订单状态不是"待支付"
    // 3. 用户已绑定pushUid
    // 4. 用户开启了touristOrderNotice
    // 5. 订单未被推送过（pushStatus=0 或 NULL）
    $orders = $DB->query("SELECT o.*, u.pushUid, u.touristOrderNotice 
        FROM qingka_wangke_order o 
        JOIN qingka_wangke_user u ON o.uid = u.uid 
        WHERE (o.type = 'tourist' OR o.type = 'tourist1')
        AND o.status != '待支付'
        AND u.pushUid IS NOT NULL 
        AND u.touristOrderNotice = '1' 
        AND (o.pushStatus = '0' OR o.pushStatus IS NULL)
        LIMIT 20");
    
    $count = 0;
    
    while ($order = $DB->fetch($orders)) {
        // 构建订单信息
        $orderInfo = [
            'oid' => $order['oid'],
            'kcname' => $order['kcname'],
            'user' => $order['user'],
            'school' => $order['school'],
            'status' => $order['status'],
            'time' => $order['addtime'],
            'shoujia' => $order['shoujia'],
            'fees' => $order['fees'],
            'remarks' => $order['remarks'] ?? '无备注'
        ];
        
        // 发送推送
        $result = sendTouristOrderNotice($wxpusher, $order['pushUid'], $orderInfo);
        
        // 更新订单推送状态
        $pushStatus = $result ? '1' : '2';
        $DB->query("UPDATE qingka_wangke_order SET pushStatus = '$pushStatus' WHERE oid = '{$order['oid']}'");
        
        $count++;
        sleep($pushDelay); // 延迟，避免API限制
    }
    
    logMessage("接单商城订单推送检查完毕，处理 {$count} 条记录");
} 